/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       adventure_frame.h

	$Header: /game/adventure_frame.h $

	$NoKeywords: $

 ************************************************************************/
#ifndef ADVENTURE_FRAME_H_INCLUDED
#define ADVENTURE_FRAME_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#pragma warning( disable: 4786 )


#include "adventure_map_ptr.h"
#include "adventure_map_window_ptr.h"
#include "animated_window_ptr.h"
#include "animation_ptr.h"
#include "army_list.h"
#include "army_ptr.h"
#include "bitmap_cursor.h"
#include "button_ptr.h"
#include "cached_ptr.h"
#include "counted_thread_safe_ptr.h"
#include "creature_array_window_ptr.h"
#include "creature_detail_display.h"
#include "game_window.h"
#include "game_time.h"
#include "handler.h"
#include "idle_processor.h"
#include "material_display.h"
#include "override_input_handler.h"
#include "scrollbar_ptr.h"
#include "shroud_removers.h"
#include "shared_ptr.h"
#include "text_window_ptr.h"
#include "town_ptr.h"
#include "vector_set.h"

#include <map>

class	t_actor;
class	t_adventure_frame;
class	t_adventure_map;
class	t_adventure_map_window;
class	t_adventure_object;
class	t_adventure_path_finder;
class	t_army_list_window;
class	t_bitmap_group;
class	t_button_cache;
enum	t_combat_result;
class	t_creature_array;
class	t_creature_stack;
class   t_mini_map_window;
struct	t_nm_combat_start;
struct	t_nm_combat_results;
struct	t_nm_map_full_update;
enum	t_direction;
class	t_mini_map_window;
class   t_saved_combat;
struct	t_spellbook_window_data;
enum	t_terrain_type;
class   t_town_list;
class	t_town_list_window;
class	t_visibility_point;


int const k_days_per_week = 7;
int const k_weeks_per_month = 4;
int const k_days_per_month = k_days_per_week * k_weeks_per_month;

enum t_game_over_result
{
	k_game_over_result_lose,
	k_game_over_result_win,
	k_game_over_result_count
};

// ----------------------------------------------------
// win/lose window to handle post game cinematics
// ----------------------------------------------------
class t_win_lose_window	: public t_window
{
public:
	typedef t_owned_ptr<t_override_input> t_override_input_ptr;

	t_win_lose_window( t_window* parent, t_handler callback_handler );
	void								cancel();
	void								end( t_window* );

protected:
	t_override_input_ptr				m_input_handler;	
	t_handler		 					m_callback_handler;	
	bool								m_end_handled;
};

// ---------------------------------------------------
// class for animated day scroll
// ---------------------------------------------------
class t_day_scroll : public t_idle_processor
{
public:
	t_day_scroll();

	void		 init( t_screen_point point, int day, t_window* parent );
	void		 new_day( int day );
	virtual void on_idle();
protected:
	enum t_state
	{
		k_halted,
		k_rolling_left,
		k_rolling_right
	};

	t_bitmap_group_ptr  m_bitmaps;
	int                 m_day;
	t_window_ptr        m_edge;
	int                 m_minimum_width;
	int                 m_maximum_width;
	t_state				m_state;
	t_text_window_ptr   m_text;
	t_window_ptr        m_window;
};

// ---------------------------------------------------
// class for animated day scroll
// ---------------------------------------------------
class t_turn_duration_timer : public t_idle_processor
{
public:
	t_turn_duration_timer();
	void    init( t_adventure_frame* );
	virtual void on_idle();

protected:
    t_adventure_frame*      m_frame;
    t_adventure_map*        m_map;
};

typedef t_counted_ptr<t_turn_duration_timer> t_turn_duration_timer_ptr;

// ---------------------------------------------------
// class for interface elements of adventure window
// ---------------------------------------------------
class t_adventure_frame : public t_window, public t_idle_processor
{
public:
	typedef t_vector_set< t_map_point_2d >	t_tile_point_set;
	typedef t_owned_ptr<t_override_input>	t_override_input_ptr;

	t_adventure_frame( t_adventure_map* adventure_map, t_window* parent );
	virtual ~t_adventure_frame();

	bool  ai_cast_summon_boat( t_creature_array& army, t_hero& hero, t_adv_map_point const& point );
	void	add_to_non_permanent_windows_list( t_window_ptr window );
	bool	attach_replay_adventure_map( );
	bool	attach_normal_adventure_map( );
	bool	cast_adventure_spell( t_creature_array&	army, int caster_slot, t_spellbook_window_data const&	spell_data, t_town* town = 0 );
	void	center_view_on_selected_creature();
	void	check_for_event_triggers();
	t_army* create_army( t_adventure_object* source, t_army* army, t_army* temp_army );
	void	destroy_army( t_army_ptr army );
	void	do_end_game_dialogs();
	void	do_end_turn();
	void	do_quit( t_button* );
	void	do_save_and_quit( t_button* );
	void	do_town_dialog( t_town * town, t_army * army );
	void	evaluate_victory_condition();
  void  force_end_turn();
	void	game_over( t_game_over_result result, int team_num = -1 );
	int		get_elapsed_turn_time() const;
	t_adventure_map* get_map() const;
	t_adventure_map_window* get_map_window() const;
	t_mini_map_window* get_mini_map_window();
	t_adventure_path_finder* get_path_finder() const;
  int   get_saved_elapsed_time() const;
	t_army* get_selected_army() const;
	t_creature_stack* get_selected_creature() const;
	int   get_selected_creature_slot() const;
	t_creature_array*        get_selected_creatures() const;
	int						 get_team_view() const;
	void					 hide_player_info();
	void					 main_menu();
    void					 marketplace();
	virtual bool			 menu_click( int id );
    virtual void			 mouse_move( t_mouse_event const& event );
	void					 move_selected_army( t_button* );
	virtual void				on_close();
	virtual void				on_idle();
	virtual void				on_size_change( t_screen_rect const& rect );
	void						play_win_lose_cinematic();
	void						reset_turn_time();
	void						resize_view( t_screen_rect const& new_size_pos);
	void						pause_turn_time();
	void						puzzle_window();
	void						puzzle_window_click( t_button* );
    void						quest_log_click( t_button* );
    void						quest_log_window();
	void						refresh_path();
	void						replay_turn();
	void						replay_turn_finish();
	void						reset_pathfinder();
	void						run_army_dialog( t_army * army, t_army * adjacent_army = NULL, int slot = -1, 
												 bool trigger_events = true, t_handler enemy_attack_handler = t_handler() );
	void						select_army( t_army* army );
	void						select_first_item();
	void						select_town( t_town* town );
	void						set_day( int day );
	void						show_player_info();
	void						sleep_selected_army( bool is_asleep );
	void						set_team_view();
	void						set_team_view(int new_team_view);
	void						set_view_level( int new_view_level );
	void						start_army_moving( t_army* army );
	void						start_new_game( t_adventure_map_ptr new_map );
	void						start_saved_game();

	void						toggle_players_as_ai( bool all_ai );
	void						update();
	void						update_army();
	bool						update_army( t_army* army );
	void						update_armies();
	void						update_buttons();
	void						update_funds();
	void						update_towns();
	void						unpause_turn_time();


protected:
    void        autosave_game();
	bool		cast_endurance( t_creature_array&			   army,
								int							   caster_slot,
								t_spellbook_window_data const& spell_data );
	bool		cast_healing( t_creature_array&				 army,
							  int							 caster_slot,
		                      t_spellbook_window_data const& spell_data );
	bool		cast_mana( t_creature_array&			  army,
						   int							  caster_slot,
						   t_spellbook_window_data const& spell_data );
	bool		cast_mass_healing( t_creature_array&			  army, 
		                           int							  caster_slot,
		                           t_spellbook_window_data const& spell_data );
	bool		cast_mire( t_creature_array&			  army,
						   int							  caster_slot,
						   t_spellbook_window_data const& spell_data,
						   t_town*						  town );
	bool		cast_pathfinding( t_creature_array&				 army,
								  int							 caster_slot,
								  t_spellbook_window_data const& spell_data );
	bool		cast_summon_boat( t_creature_array&				 army,
								  int							 caster_slot,
								  t_spellbook_window_data const& spell_data );
	bool		cast_targeted_adventure_spell( t_creature_array&			  army, 
											   int							  caster_slot,
											   t_spellbook_window_data const& spell_data );
	bool		cast_town_gate( t_creature_array&			   army,
								int							   caster_slot,
								t_spellbook_window_data const& spell_data,
								t_town*						   town );
	bool		cast_visions( t_creature_array&				 army,
							  int							 caster_slot,
							  t_spellbook_window_data const& spell_data );
	void	    cheat_learn_skill();
	void		create_adventure_map_window();
	t_button*   create_button( char const*			 layer_name, 
						       t_button_cache const& button_cache,
							   t_screen_point        origin );
	void		create_buttons();
	void		creature_double_click( t_creature_array_window* window, int slot );
    void        dig();
	void		end_turn_animation_finished( t_window* animation );
	void		end_turn_click( t_button* );
	void		free_experience();
	void		game_menu( t_button* );
	t_direction get_scroll_direction( t_screen_point const& point, int& distance ) const;
	void		gold_bar_clicked( t_button* );
	void		initialize();
    void        kingdom_overview();
	void        kingdom_overview_click( t_button* );
	void		kingdom_trade();
	void		layer_view_click( t_button* );
	void		learn_spells_cheat();
	void		load_game();
	void		materials_cheat();
	void		new_campaign();
	void		new_scenario();
	void		options();
	void		process_arriving_caravans();
	void		process_arriving_caravans_list_waiting_caravans( t_town_list & wait_in_own_town_list, int & wait_in_own_count, 
																 t_town_list & wait_in_allied_town_list, int & wait_in_allied_count,
																 t_town_list & wait_near_enemy_town_list, int & wait_near_enemy_count ) const;
	void		process_arriving_caravans_generate_external_armies( t_town_list & dropped_in_external_army_for_foreign_town_list, 
																	int & dropped_in_external_army_for_foreign_count, 
																	t_town_list & dropped_in_external_army_for_own_town_list, 
																	int & dropped_in_external_army_for_own_count, 
																	t_army_list & created_armies );
	void		process_arriving_caravans_move_to_garrisons();
	void		quit();
	void		resources_bar_clicked( t_button* );
	void		restart_game();
	bool		save_game();
	void		save_handler();
    void        scenario_info();
	void		select_creature( t_creature_array_window* window, int slot );
	void		set_army_mode( bool army_mode );
	void		set_resolution( int width );
	void		show_army_dialog( t_army* army );
	void		show_town_dialog( t_town* town );
	void        spellbook_click( t_button* );
	void		start_human_turn();
	void		system_menu( t_button* );
    void        thieves_guild();
	void		unlimited_move();
	void		view_caravan();
	void		view_world();

	t_adventure_map_ptr						m_adventure_map;
	t_adventure_map_ptr						m_adventure_normal_map;
	t_adventure_map_ptr						m_adventure_replay_map;
	t_adventure_map_window_ptr				m_adventure_map_window;
	bool									m_allow_scrolling;
	t_creature_array_window_ptr				m_army_display;
	t_counted_ptr<t_army_list_window>		m_army_list;
	t_creature_detail_display				m_creature_detail;
	t_day_scroll							m_day_scroll;
	int										m_distance;
	t_animation_ptr							m_end_turn_animation;
	t_animated_window_ptr					m_end_turn_animation_window;
	t_button_ptr							m_end_turn_button;
	t_button_ptr							m_gold_bar;
	bool									m_in_army_mode;
	bool									m_in_replay_mode;
	t_cached_ptr<t_bitmap_group>			m_interface_background;
	t_window_list							m_interface_windows;	
	t_button_ptr							m_marketplace_button;
	t_material_display						m_material_display;
	t_material_display						m_material_display_gold;
	t_counted_ptr<t_mini_map_window>		m_mini_map;
	t_direction								m_mouse_direction;
	t_button_ptr							m_move_army_button;
	std::vector<t_window_ptr>               m_non_permanent_windows;
	t_mouse_window_ptr						m_normal_cursor;
	t_button_ptr							m_overview_button;
	t_shared_ptr<t_adventure_path_finder>	m_path_finder;
	t_button_ptr							m_resources_bar;
	t_override_input_ptr					m_replay_input_handler;
	t_counted_ptr<t_text_window>			m_replay_text;
	t_window_ptr							m_right_bar;
	t_army_ptr								m_selected_army;
	t_town_ptr								m_selected_town;
	t_bitmap_cursor							m_scroll_cursor;
	t_uint32								m_scroll_distance;
	t_window_list							m_stats_icons;
	t_scrollbar_ptr							m_army_scrollbar;
	t_scrollbar_ptr							m_town_scrollbar;
	bool									m_scrolling;	
	t_button_ptr							m_spell_button;
	t_button_ptr							m_surface_button;
	int										m_team_view;
	t_town_list_window*						m_town_list;
    int                                     m_turn_time;
    int                                     m_turn_time_elapsed;
	t_turn_duration_timer                   m_turn_duration_timer;
	t_button_ptr							m_underground_button;

private:
	t_game_over_result						m_game_result;
	int										m_winner_team;
	t_win_lose_window *						m_win_lose_window;
};

inline t_adventure_path_finder* t_adventure_frame::get_path_finder() const
{
	return m_path_finder.get();
}

inline void t_adventure_frame::update_funds()
{
	m_material_display.update();
	m_material_display_gold.update();
}

inline int t_adventure_frame::get_elapsed_turn_time() const
{
    return (get_time() - m_turn_time);
}

inline int t_adventure_frame::get_saved_elapsed_time() const
{
    return m_turn_time_elapsed;
}


// --------------------------------------------------------------------------
// class which calls t_adventure_frame::hide_player_info() in its constructor
// and t_adventure_frame::show_player_info() in its destructor
// --------------------------------------------------------------------------

class t_player_info_hider
{
public:
	explicit t_player_info_hider( t_adventure_frame & frame );
	~t_player_info_hider();

private:
	t_adventure_frame &	m_frame;
};

inline t_player_info_hider::t_player_info_hider( t_adventure_frame & frame )
	:	m_frame( frame )
{
	m_frame.hide_player_info();
}

inline t_player_info_hider::~t_player_info_hider()
{
	m_frame.show_player_info();
}

bool write_saved_game( t_window* parent, t_adventure_map* adventure_map, 
					   t_saved_combat* saved_combat );



#endif // ADVENTURE_FRAME_H_INCLUDED
